#include <fstream>
#include "paintdata.h"
#include "../geometry/rayintersections.h"

paint_data_t::paint_data_t()
{
}

paint_data_t::paint_data_t(polygon_data_t const & polygon) : polygon_(polygon), cell_size_(50)
{
    if(polygon_.size() > 0)
    {
        current_contour_ = 0;
    }
    else
    {
        add_new_contour();
    }
    grid_ = grid_t(get_polygon(polygon_), cell_size_);
}

void paint_data_t::current_contour(size_t current_contour)
{
    if(current_contour < polygon_.size())
    {
        current_contour_ = current_contour;
        emit paint_data_t::updated();
    }
}

size_t paint_data_t::current_contour() const
{
    return current_contour_;
}

polygon_t paint_data_t::polygon() const
{
    return get_polygon(polygon_);
}

void paint_data_t::to_process_point(point_t const & point)
{
    polygon_data_t remember = polygon_;
    if (current_point_ == 0)
    {
        current_point_ = find_point(point);
        if (current_point_ == 0)
        {
            polygon_.at(current_contour_).push_back(point);
        }
    }
    else
    {
        *current_point_ = point;
        current_point_ = 0;
    }

    polygon_t poly = get_polygon(polygon_);
    bool flag = false;
    for(size_t i = 0; i < poly.size(); ++i)
    {
        if(poly[i].size() < remember[i].size())
        {
            flag = true;
            break;
        }
    }

    if(flag)
    {
        polygon_ = remember;
        grid_ = grid_t(get_polygon(polygon_), cell_size_);
    } else {
        grid_ = grid_t(poly, cell_size_);
    }
    
    emit paint_data_t::updated();
}

point_t * paint_data_t::find_point(point_t const & point) {
    point_t * polygon_pos;
    for (int x = point.x - 10; x != point.x + 10; ++x)
    {
        for (int y = point.y - 10; y != point.y + 10; ++y)
        {
            polygon_pos = find(point_t(x, y), polygon_);
            if (polygon_pos != 0) return polygon_pos;
            if(point_t(x, y) == user_point_) return & user_point_;
        }
    }
    return 0;
}

bool paint_data_t::is_current_point(point_t const & point) const
{
    return ((current_point_ != 0) && point == *current_point_);
}

void paint_data_t::save() const
{
    std::ofstream out("output");
    out << cell_size_ << " " << polygon_ /*<< grid_*/ << std::endl;
    for(size_t i = 0; i < grid_.size(); ++i)
    {
        out << grid_[i].center() << " " << grid_[i].center_in() << std::endl;
    }
    out.close();
}

void paint_data_t::add_new_contour() {
    std::vector<point_t> points;
    points.push_back(point_t(100, 100));
    points.push_back(point_t(50, 50));
    contour_data_t contour(points.begin(), points.end());
    polygon_.push_back(contour);
    current_contour_ = polygon_.size() - 1;
    grid_ = grid_t(get_polygon(polygon_), cell_size_);
    emit paint_data_t::updated();
}

void paint_data_t::remove(size_t contour_num)
{
    if(contour_num < polygon_.size())
    {
        polygon_.erase(polygon_.begin() + contour_num);
        if(contour_num == current_contour_)
        {
            current_contour_ = polygon_.size() - 1;
        }
    }
    emit paint_data_t::updated();
}

point_t const & paint_data_t::user_point() const
{
    return user_point_;
}

bool paint_data_t::point_is_in() const
{
    //return belongs(start_ray_, get_polygon(polygon_));
    return grid_.inside(user_point_);
}

grid_t const & paint_data_t::grid() const
{
    return grid_;
}

double paint_data_t::cell_size() const
{
    return cell_size_;
}

void paint_data_t::cell_size(double new_size)
{
    cell_size_ = new_size;
    grid_ = grid_t(get_polygon(polygon_), cell_size_);
    emit paint_data_t::updated();
}
